﻿using AccessCompare.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AccessCompare
{
    public class SchemaComparer
    {
        #region VARIABLE DECLARATIONS

        private string sourceDatabase = string.Empty;
        private string destinationDatabase = string.Empty;
        private SchemaReader _sourceReader;
        private SchemaReader _destinationReader;

        #endregion

        #region PROPERTIES

        /// <summary>
        /// Gets the Source reader
        /// </summary>
        private SchemaReader SourceReader
        {
            get
            {
                if(_sourceReader == null)
                {
                    _sourceReader = new SchemaReader(sourceDatabase);
                }

                return _sourceReader;
            }
        }

        /// <summary>
        /// Gets the Destination Reader
        /// </summary>
        private SchemaReader DestinationReader
        {
            get
            {
                if (_destinationReader == null)
                {
                    _destinationReader = new SchemaReader(destinationDatabase);
                }

                return _destinationReader;
            }
        }

        /// <summary>
        /// Gets the Source schema. If the Compare method is not called it will return empty list
        /// </summary>
        public List<Table> SourceSchema
        {
            get
            {
                return SourceReader.Schema;
            }
        }

        /// <summary>
        /// Gets the Destination schema. If the Compare method is not called it will return empty list
        /// </summary>
        public List<Table> DestinationSchema
        {
            get
            {
                return DestinationReader.Schema;
            }
        }

        #endregion

        #region CONSTRUCTOR

        /// <summary>
        /// Schema comparer
        /// </summary>
        /// <param name="source">The source path of the database</param>
        /// <param name="destination">The destination path of the database</param>
        public SchemaComparer(string source, string destination)
        {
            if (string.IsNullOrEmpty(source) && string.IsNullOrEmpty(destination))
            {
                throw new Exception("Source and Destination Database path needs to be provided!");
            }
            else
            {
                sourceDatabase = source;
                destinationDatabase = destination;
            }
        }

        #endregion

        #region PUBLIC METHODS

        /// <summary>
        /// Compares the two databases
        /// </summary>
        public void Compare()
        {
            SourceReader.Load();
            DestinationReader.Load();

            CompareSchemas(SourceReader.Schema, DestinationReader.Schema);
        }

        #endregion

        #region PRIVATE METHODS

        /// <summary>
        /// Compares the tables schemas of the databases
        /// </summary>
        /// <param name="source">The source tables</param>
        /// <param name="destination">The destination tables</param>
        private void CompareSchemas(List<Table> source, List<Table> destination)
        {
            foreach (Table sourceTable in source)
            {
                Table destinationTable = (from d in destination
                                             where d.Name.Equals(sourceTable.Name)
                                             select d).FirstOrDefault();

                if (destinationTable != null)
                {
                    sourceTable.TableStatus = Status.Equal;
                    destinationTable.TableStatus = Status.Equal;

                    CompareColumns(sourceTable.Columns, destinationTable.Columns);

                }
                else
                {
                    destinationTable = new Table();
                    destinationTable.Name = sourceTable.Name;
                    destinationTable.TableStatus = Status.Missing;
                    sourceTable.TableStatus = Status.Equal;
                }
            }
        }

        /// <summary>
        /// Compares the schemas of the columns in the table
        /// </summary>
        /// <param name="source">Sorce columns</param>
        /// <param name="destination">Destination columns</param>
        private void CompareColumns(List<Column> source, List<Column> destination)
        {
            foreach (Column sourceColumn in source)
            {
                Column destinationColumn = (from c in destination
                                               where c.Name.Equals(sourceColumn.Name)
                                               select c).FirstOrDefault();

                if (destinationColumn != null)
                {
                    if (destinationColumn.ColumnType.Equals(sourceColumn.ColumnType))
                    {
                        destinationColumn.ColumnStatus = Status.Equal;
                        sourceColumn.ColumnStatus = Status.Equal;
                    }
                    else
                    {
                        destinationColumn.ColumnStatus = Status.Different;
                        sourceColumn.ColumnStatus = Status.Equal;
                    }
                }
                else
                {
                    destinationColumn = new Column(sourceColumn.Name, sourceColumn.ColumnType);
                    destinationColumn.ColumnStatus = Status.Missing;
                }

            }
        }

        #endregion
    }
}
